/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
  <file> UlsStream.cpp </file>
  <brief>
 	Implementing the wrapper class of ulslex_t
    This file is part of ULS, Unified Lexical Scheme.
  </brief>
  <author>
    Stanley J. Hong <babel96@gmail.com>, 2011.
  </author>
*/

#include <iostream>
#include <string>

#include "UlsStream.h"
#include "uls.h"
#include "common.h"

using namespace std;
using namespace ULS;

// <brief>
// A constructor which accepts UlsLex as first parameter.
// 'UlsLex' is the the class for lexical analysis defined in the same namespace 'ULS'.
// </brief>
// <parm name="ulslex">An object for lexical analysis</parm>
// <return>none</return>
UlsStream::UlsStream(UlsLex& ulslex)
{
	uls = ulslex.GetLexCore();
	uls_init_stream(&uls_hdr, uls, -1);
	fd_out = -1;
}

// <brief>
// The destuctor of UlsStream.
// </brief>
// <return>none</return>
UlsStream::~UlsStream()
{
	uls = NULL;
}

// <brief>
// This create a uls-file, output file, named by 'filepath' and
// writes some attributes to the ULS-header in the file.
// </brief>
// <parm name="filepath">The name of output-file.</parm>
// <parm name="mode">The type of file, The default value ULS_STREAM_BIN_LE is for creating the file of little-endian</parm>
// <parm name="subtag">The value of this is stored in an attribute in uls-file as 'TAG:'</parm>
// <return>true/false</return>
bool UlsStream::createStream(string& filepath, int mode, string subtag)
{
	int fd;

	if ((fd = uls_open(filepath.c_str(),
			O_CREAT | O_TRUNC | O_WRONLY | _O_BINARY, 0644)) < 0) {
		return false;
	}

	if (uls_create_stream(&uls_hdr, uls, fd, mode, (char *) subtag.c_str()) < 0) {
		uls_close(fd);
		return false;
	}

	fd_out = fd;
	return true;
}

// <brief>
// starts streaming and store the sequence of tokens to filepath.
// The sequence constitutes the body of the file.
// You can call this method multiple times with different 'filepath'.
// </brief>
// <parm name="filepath">The path of input file</parm>
// <return>0 if it succeeds, otherwise -1</return>
int UlsStream::startStream(string& filepath)
{
	uls_stream_t in_hdr;
	int stat = 0;

	if (uls_open_stream_file(filepath.c_str(), &in_hdr) < 0) {
		return -1;
	}

	if (uls_start_stream(&uls_hdr, &in_hdr, 0) < 0) {
		stat = -1;
	}

	uls_close_stream(&in_hdr);

	return stat;
}

// <brief>
// This finalizes the streaming and closes the output-file.
// </brief>
// <return>none</return>
void UlsStream::closeStream(void)
{
	uls_close_stream(&uls_hdr);
	uls_close(fd_out);
	fd_out = -1;
}

// <brief>
// reads the head informaton of uls-file indicated by 'fd' 
// stores it to the field 'uls_hdr'.
// </brief>
// <parm name="fd">the file-descriptor of uls-stream file (*.uls)</parm>
// <return>none</return>
void UlsStream::readUlsHeader(int fd)
{
	uls_open_stream_fd(fd, &uls_hdr);
}
